`ifndef PROC_UNIT
`define PROC_UNIT

module reg_unit #(
	`include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
)(
	output reg [WORD_WD -1:0] data_out,
	input	   [WORD_WD -1:0] data_in,
	input 					  load, clk, rst_n
);

	always @(posedge clk)begin
		if(rst_n == 1'b0)begin
			data_out <= {WORD_WD{1'b0}};
		end
		else if(load == 1'b1)begin
			if(DISPLAY_EN == 1) $display("%0t, %m, data_out update to 'b%8b('h%2h-'d%0d)", $realtime, data_in, data_in, data_in);
			data_out <= data_in;
		end
		else begin
			data_out <= data_out;
		end
	end

endmodule//: reg_unit

module program_count #(
	`include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
)(
	output reg [WORD_WD -1:0] count_out,
	input	   [WORD_WD -1:0] count_in,
	input 					  load, incr, clk, rst_n
);

	always @(posedge clk)begin
		if(rst_n == 1'b0)begin
			count_out <= {WORD_WD{1'b0}};
		end
		else if(load == 1'b1)begin
			count_out <= count_in;
		end
		else if(incr == 1'b1)begin
			count_out <= count_out + 'h1;
		end
		else begin
			count_out <= count_out;
		end
	end

endmodule//: program_count

module mux_5sel1 #(
	`include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
)(
	output reg [WORD_WD -1:0] mux_out,
	input  [WORD_WD -1:0]     mux_in0, mux_in1, mux_in2, mux_in3, mux_in4,
	input  [SEL1_WD  -1:0]    sel
);

	always @(*)begin
	    case(sel)
			'h0: mux_out = mux_in0;
			'h1: mux_out = mux_in1;
			'h2: mux_out = mux_in2;
			'h3: mux_out = mux_in3;
			'h4: mux_out = mux_in4;
			default: mux_out = {WORD_WD{1'bx}};
		endcase		
	end

endmodule//: mux_5sel1

module mux_3sel1 #(
	`include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
)(
	output reg [WORD_WD -1:0] mux_out,
	input  [WORD_WD -1:0]     mux_in0, mux_in1, mux_in2,
	input  [SEL2_WD  -1:0]    sel
);

	always @(*)begin
	    case(sel)
			'h0: mux_out = mux_in0;
			'h1: mux_out = mux_in1;
			'h2: mux_out = mux_in2;
			default: mux_out = {WORD_WD{1'bx}};
		endcase		
	end

endmodule//: mux_3sel1

module alu_unit #(
	`include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
)(
	output reg [WORD_WD -1:0]   alu_out,
	output     				    zero_flag,
	input	   [WORD_WD -1:0]   alu_in1, alu_in2,
	input	   [OPCODE_WD -1:0] opcode
);

	always @(*)begin
		case(opcode)
			NOP:	alu_out = 'h0;
			ADD:	alu_out = alu_in2 + alu_in1;
			SUB:	alu_out = alu_in2 - alu_in1;		
			AND:	alu_out = alu_in2 & alu_in1;
			NOT:	alu_out = ~alu_in2;
			default:alu_out = 'hx;
		endcase
	end
	
	assign zero_flag = ~(|alu_out);

endmodule//: alu_unit
`endif